package com.yenroc.invoice.service.impl;

import com.itextpdf.kernel.geom.PageSize;
import com.yenroc.invoice.pojo.BaseInvoiceCreateDTO;
import com.yenroc.invoice.pojo.BaseInvoiceDetailDTO;
import com.yenroc.invoice.pojo.CommonInvoiceDTO;
import com.yenroc.invoice.pojo.CreateInvoiceResult;
import com.yenroc.invoice.pojo.xml.IssuItemInformationXmlDTO;
import com.yenroc.invoice.pojo.xml.SpecificInformationXmlDTO;
import com.yenroc.invoice.service.AbstractInvoice;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
public class BaseInvoiceServiceImpl extends AbstractInvoice {
    /**
     * 数字化电子发票（基础版）发票创建
     *
     * @param createDTO {@link BaseInvoiceCreateDTO BaseInvoiceCreateDTO}
     * @return JSONObject
     */
    public <T extends CommonInvoiceDTO> CreateInvoiceResult createInvoice(T createDTO) {
        return invokeInvoice(createDTO);
    }

    @Override
    protected Document getDocument() {
        try {
//            return Jsoup.parse(new File("src/main/resources/static/template/baseInvoice.html"), "utf-8");
//            return Jsoup.parse(new File(new ClassPathResource("/static/template/baseInvoice.html").getURI()), "utf-8");// 服务器找不到
            return Jsoup.parse(this.getClass().getResourceAsStream("/static/template/baseInvoice.html"),"utf-8", "");
        } catch (Exception e) {
            log.error("读取模板html error:", e);
        }
        return null;
    }

    @Override
    protected Document getFirstPageDocument() {
        return null;
    }

    @Override
    protected Document getMultiPageDocument() {
        return null;
    }

    @Override
    protected <T extends CommonInvoiceDTO> void fillInvoiceDetail(Document document, T dto) {
        // 填充发票明细
        Element goodsTbodyElement = document.getElementById("goodsTbody");
        if (goodsTbodyElement == null) {
            goodsTbodyElement = document.createElement("tbody");
            goodsTbodyElement.id("goodsTbody");
            goodsTbodyElement.addClass("goodsTbody");
        }
        BaseInvoiceCreateDTO baseInvoiceCreateDTO = (BaseInvoiceCreateDTO) dto;
        List<BaseInvoiceDetailDTO> detailPoList = baseInvoiceCreateDTO.getDetailList();
        for (BaseInvoiceDetailDTO it : detailPoList) {
            Element trElement = document.createElement("tr");
            trElement.addClass("goodsTableTr");
            trElement.append(String.format("<td class=\"goodsTable1Col\">%s</td>", it.getGoodsName()));
            trElement.append(String.format("<td class=\"goodsTable2Col\">%s</td>", it.getGoodsSpecification() == null ? "" : it.getGoodsSpecification()));
            trElement.append(String.format("<td class=\"goodsTable3Col\">%s</td>", it.getGoodsUnit() == null ? "" : it.getGoodsUnit()));
            trElement.append(String.format("<td class=\"goodsTable4Col\">%s</td>", it.getGoodsQuantity() == null ? "" : it.getGoodsQuantity()));
            trElement.append(String.format("<td class=\"goodsTable5Col\">%s</td>", it.getGoodsPrice() == null ? "" : it.getGoodsPrice()));
            trElement.append(String.format("<td class=\"goodsTable6Col\">%s</td>", it.getGoodsTotalPrice()));
            trElement.append(String.format("<td class=\"goodsTable7Col\">%s</td>", formatTaxRate(it.getGoodsTaxRate(), it.getPreferentialPolicy())));
            trElement.append(String.format("<td class=\"goodsTable8Col\">%s</td>", formatGoodTax(it.getGoodsTaxRate(), it.getGoodsTax(), it.getPreferentialPolicy())));
            goodsTbodyElement.appendChild(trElement);
        }
    }

    @Override
    public <T extends CommonInvoiceDTO> void fillInvoiceItemDetail(Document document, T dto) {
        // 填充发票明细
        Element goodsTbodyElement = document.getElementById("goodsTbody");
        if (goodsTbodyElement == null) {
            goodsTbodyElement = document.createElement("tbody");
            goodsTbodyElement.id("goodsTbody");
            goodsTbodyElement.addClass("goodsTbody");
        }
        BaseInvoiceCreateDTO baseInvoiceCreateDTO = (BaseInvoiceCreateDTO) dto;
        List<BaseInvoiceDetailDTO> detailPoList = baseInvoiceCreateDTO.getDetailList();
        for (BaseInvoiceDetailDTO it : detailPoList) {
            Element trElement = document.createElement("tr");
            trElement.addClass("goodsTableTr");
            trElement.append(String.format("<td class=\"goodsTable1Col\">%s</td>", it.getGoodsName()));
            trElement.append(String.format("<td class=\"goodsTable2Col\">%s</td>", it.getGoodsSpecification() == null ? "" : it.getGoodsSpecification()));
            trElement.append(String.format("<td class=\"goodsTable3Col\">%s</td>", it.getGoodsUnit() == null ? "" : it.getGoodsUnit()));
            trElement.append(String.format("<td class=\"goodsTable4Col\">%s</td>", it.getGoodsQuantity() == null ? "" : it.getGoodsQuantity()));
            trElement.append(String.format("<td class=\"goodsTable5Col\">%s</td>", it.getGoodsPrice() == null ? "" : it.getGoodsPrice()));
            trElement.append(String.format("<td class=\"goodsTable6Col\">%s</td>", it.getGoodsTotalPrice()));
            trElement.append(String.format("<td class=\"goodsTable7Col\">%s</td>", formatTaxRate(it.getGoodsTaxRate(), it.getPreferentialPolicy())));
            trElement.append(String.format("<td class=\"goodsTable8Col\">%s</td>", formatGoodTax(it.getGoodsTaxRate(), it.getGoodsTax(), it.getPreferentialPolicy())));
            goodsTbodyElement.appendChild(trElement);
        }
    }

    @Override
    protected <T extends CommonInvoiceDTO> void fillInvoiceTypeDetail(Document document, T dto) {

    }

    @Override
    protected <T extends CommonInvoiceDTO> PageSize calculatePageSize(T dto) {
        BaseInvoiceCreateDTO base = (BaseInvoiceCreateDTO) dto;
        // 计算高度
        int lengthCount = base.getDetailList().stream()
                .mapToInt(item -> Math.max(
                        item.getGoodsName().length() > 12 ? (int) Math.ceil((float) item.getGoodsName().length() / 12) : 1,
                        item.getGoodsPrice() != null && item.getGoodsPrice().toString().length() > 15 ? (int) Math.ceil((float) item.getGoodsPrice().toString().length() / 15) : 1)
                ).sum();
        if (lengthCount <= 7) {
            return new PageSize(595f, 391f);
        } else if (lengthCount == 8) {
            return new PageSize(595f, 394f);
        } else {
//            float i = calculateHeightIncrease(lengthCount);
//            float overHeight = (lengthCount - 8) * 11 + i;
            // TODO hyp 计算高度调整
            float overHeight = (lengthCount - 8) * 11.3F;
            return new PageSize(595f, 394f + overHeight);
        }
    }

    @Override
    protected <T extends CommonInvoiceDTO> PageSize calculatePageSize2(T dto) {
        return calculatePageSize(dto);
    }

    @Override
    protected <T extends CommonInvoiceDTO> List<String> getHtmlStrList(String qrCode, String invoiceStamp, T dto) {
        List<String> list = new ArrayList<>();
        String htmlStr = getInvoiceHtml(qrCode, invoiceStamp, null, dto);
        list.add(htmlStr);
        return list;
    }

    @Override
    protected <T extends CommonInvoiceDTO> SpecificInformationXmlDTO getSpecificInformation(T dto) {
        return SpecificInformationXmlDTO.builder()
                .build();
    }

    @Override
    protected <T extends CommonInvoiceDTO> List<IssuItemInformationXmlDTO> getIssuItemInformation(T dto) {
        List<IssuItemInformationXmlDTO> list = new ArrayList<>();
        BaseInvoiceCreateDTO createDTO = (BaseInvoiceCreateDTO) dto;
        List<BaseInvoiceDetailDTO> detailList = createDTO.getDetailList();
        if (detailList != null && detailList.size() > 0) {
            for (BaseInvoiceDetailDTO detail : detailList) {
                list.add(IssuItemInformationXmlDTO.builder()
                        .itemName(detail.getGoodsName())
                        .specMod(detail.getGoodsSpecification())
                        .meaUnits(detail.getGoodsUnit())
                        .quantity(detail.getGoodsQuantity())
                        .unPrice(detail.getGoodsPrice())
                        .amount(detail.getGoodsTotalPrice())
                        .taxRate(detail.getGoodsTaxRate())
                        .comTaxAm(detail.getGoodsTax())
                        .totaltaxIncludedAmount(Objects.nonNull(detail.getTotalTaxIncludedAmount()) ? detail.getTotalTaxIncludedAmount() : detail.getGoodsTotalPrice().add(detail.getGoodsTax()))
                        .taxClassificationCode(detail.getTaxClassificationCode())
                        .build());
            }
        }
        return list;
    }

}